/***************************** BEGIN LICENSE BLOCK ***************************

 The contents of this file are subject to the Mozilla Public License Version
 1.1 (the "License"); you may not use this file except in compliance with
 the License. You may obtain a copy of the License at
 http://www.mozilla.org/MPL/MPL-1.1.html
 
 Software distributed under the License is distributed on an "AS IS" basis,
 WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 for the specific language governing rights and limitations under the License.
 
 The Original Code is the "EO-SPS Framework".
 
 The Initial Developer of the Original Code is Spotimage S.A.
 Portions created by the Initial Developer are Copyright (C) 2007
 the Initial Developer. All Rights Reserved.
 
 Contributor(s): 
    Alexandre Robin <alexandre.robin@spotimage.fr>
 
******************************* END LICENSE BLOCK ***************************/

package com.spotimage.eosps;

import java.text.ParseException;
import org.vast.ogc.OGCRegistry;
import org.vast.util.DateTime;
import org.vast.util.DateTimeFormat;
import org.vast.xml.DOMHelper;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.LinearRing;
import com.vividsolutions.jts.geom.Polygon;


public class EOReportReader implements EOConstants
{
	
	public EOReportInfo parseReport(Element reportElt) throws ParseException
	{
		// prepare DOM helper to parse report xml
		DOMHelper dom = new DOMHelper("root");
		dom.getDocument().adoptNode(reportElt);
		dom.addUserPrefix(EOT_PREFIX, EOT_NAMESPACE);
		dom.addUserPrefix(EOP_PREFIX, EOP_NAMESPACE);
		dom.addUserPrefix("gml", OGCRegistry.getNamespaceURI(OGCRegistry.GML, "3.2"));
		
		if (dom.hasQName(reportElt, FEASIBILITY_STUDY_ELT))
			return parseFeasibilityStudy(dom, reportElt);
		else if (dom.hasQName(reportElt, PROGRAMMING_STATUS_ELT))
			return parseProgrammingStatus(dom, reportElt);
		else
			throw new ParseException("Unsupported report type: " + reportElt.getTagName(), 0);
	}
	
	
	protected FeasibilityStudy parseFeasibilityStudy(DOMHelper dom, Element reportElt) throws ParseException
	{
		FeasibilityStudy report = new FeasibilityStudy();
		String val;
		
		val = dom.getElementValue(reportElt, EXPIRATION_DATE_ELT);
		report.setExpirationDate(new DateTime(DateTimeFormat.parseIso(val)));
		
		val = dom.getElementValue(reportElt, ESTIMATED_COST_ELT);
		report.setEstimatedCost(Float.parseFloat(val));
		
		val = dom.getElementValue(reportElt, SUCCESS_RATE_ELT);
		report.setSuccessRate(Float.parseFloat(val));
		
		NodeList infoElts = dom.getElements(reportElt, INFO_USED_ELT);
		for (int i=0; i<infoElts.getLength(); i++)
		{
			Element infoElt = (Element)infoElts.item(i);
			val = dom.getElementValue(infoElt);
			val = val.replace(" ", "_");
			report.getInformationUsed().add(InformationType.valueOf(val));
		}
		
		parseCellsAndSegments(dom, reportElt, report);
			
		return report;
	}
	
	
	protected ProgrammingStatus parseProgrammingStatus(DOMHelper dom, Element reportElt) throws ParseException
	{
		ProgrammingStatus report = new ProgrammingStatus();
		String val;
		
		val = dom.getElementValue(reportElt, PERCENT_COMPLETION_ELT);
		report.setPercentCompletion(Float.parseFloat(val));
		
		parseCellsAndSegments(dom, reportElt, report);
		
		return report;
	}
	
	
	protected void parseCellsAndSegments(DOMHelper dom, Element reportElt, EOReportInfo eoReport) throws ParseException
	{
		NodeList segmentElts = dom.getElements(reportElt, SEGMENT_ELT);
		for (int i=0; i<segmentElts.getLength(); i++)
		{
			Element segmentElt = (Element)segmentElts.item(i);
			Segment seg = parseSegment(dom, segmentElt);
			eoReport.getSegments().add(seg);
		}
		
		NodeList cellElts = dom.getElements(reportElt, CELL_ELT);
		for (int i=0; i<cellElts.getLength(); i++)
		{
			Element cellElt = (Element)cellElts.item(i);
			GridCell cell = parseGridCell(dom, cellElt);
			eoReport.getCells().add(cell);
		}
	}
	
	
	protected Segment parseSegment(DOMHelper dom, Element segmentElt) throws ParseException
	{
		Segment segment = new Segment();
		String val;
		
		val = dom.getAttributeValue(segmentElt, ID_ATT);
		segment.setId(val);
		
		Element polyElt = dom.getElement(segmentElt, FOOTPRINT_POLY_ELT);
		Element coordsElt = dom.getElement(polyElt, FOOTPRINT_COORDS_ELT);
		segment.setFootprint(parsePolygon(dom, coordsElt));
		
		val = dom.getElementValue(segmentElt, STATUS_ELT);
		segment.setStatus(AcqStatus.valueOf(val));
		
		val = dom.getElementValue(segmentElt, SUCCESS_RATE_ELT);
		if (val != null)
			segment.setSuccessRate(Float.parseFloat(val));
		
		val = dom.getElementValue(segmentElt, ACQ_START_ELT);
		segment.setAcquisitionStartTime(new DateTime(DateTimeFormat.parseIso(val)));
			
		val = dom.getElementValue(segmentElt, ACQ_STOP_ELT);
		segment.setAcquisitionStopTime(new DateTime(DateTimeFormat.parseIso(val)));
		
		Element acqMethodElt = dom.getElement(segmentElt, ACQ_METHOD_ELT);
		if (acqMethodElt != null)
		{
			val = dom.getElementValue(acqMethodElt, PLATFORM_NAME_ELT);
			if (val != null)
				segment.setPlatformName(val);
			
			val = dom.getElementValue(acqMethodElt, PLATFORM_ID_ELT);
			if (val != null)
				segment.setPlatformID(val);
			
			val = dom.getElementValue(acqMethodElt, INSTRUMENT_NAME_ELT);
			if (val != null)
				segment.setInstrumentName(val);
			
			val = dom.getElementValue(acqMethodElt, INSTRUMENT_ID_ELT);
			if (val != null)
				segment.setInstrumentID(val);
			
			val = dom.getElementValue(acqMethodElt, INSTRUMENT_MODE_ELT);
			if (val != null)
				segment.setInstrumentMode(val);
			
			val = dom.getElementValue(acqMethodElt, RESOLUTION_ELT);
			if (val != null)
				segment.setGroundResolution(Float.parseFloat(val));
			
			val = dom.getElementValue(acqMethodElt, ORBIT_NUM_ELT);
			if (val != null)
				segment.setOrbitNumber(Integer.parseInt(val));
			
			val = dom.getElementValue(acqMethodElt, INC_ANGLE_ELT);
			if (val != null)
				segment.setIncidenceAngle(Float.parseFloat(val));
			
			val = dom.getElementValue(acqMethodElt, PITCH_ANGLE_ELT);
			if (val != null)
				segment.setPitch(Float.parseFloat(val));
			
			val = dom.getElementValue(acqMethodElt, ROLL_ANGLE_ELT);
			if (val != null)
				segment.setRoll(Float.parseFloat(val));
			
			val = dom.getElementValue(acqMethodElt, YAW_ANGLE_ELT);
			if (val != null)
				segment.setYaw(Float.parseFloat(val));
		}
		
		return segment;
	}
	
	
	protected GridCell parseGridCell(DOMHelper dom, Element cellElt) throws ParseException
	{
		GridCell cell = new GridCell();
		String val;
		
		val = dom.getAttributeValue(cellElt, ID_ATT);
		cell.setId(val);
		
		Element polyElt = dom.getElement(cellElt, FOOTPRINT_POLY_ELT);
		Element coordsElt = dom.getElement(polyElt, FOOTPRINT_COORDS_ELT);
		cell.setFootprint(parsePolygon(dom, coordsElt));
		
		val = dom.getElementValue(cellElt, STATUS_ELT);
		cell.setStatus(AcqStatus.valueOf(val));
		
		val = dom.getElementValue(cellElt, SUCCESS_RATE_ELT);
		cell.setSuccessRate(Float.parseFloat(val));
		
		val = dom.getElementValue(cellElt, SUCCESS_DATE_ELT);
		if (val != null)
			cell.setEstimatedSuccessDate(new DateTime(DateTimeFormat.parseIso(val)));
			
		val = dom.getElementValue(cellElt, LAST_ATTEMPT_ELT);
		if (val != null)
			cell.setLastAttemptDate(new DateTime(DateTimeFormat.parseIso(val)));
			
		val = dom.getElementValue(cellElt, NEXT_ATTEMPT_ELT);
		if (val != null)
			cell.setNextAttemptDate(new DateTime(DateTimeFormat.parseIso(val)));
		
		val = dom.getElementValue(cellElt, REMAINING_ATTEMPTS_ELT);
		if (val != null)
			cell.setRemainingAttempts(Integer.parseInt(val));
		
		return cell;
	}
	
	
	protected Polygon parsePolygon(DOMHelper dom, Element polyElt)
	{
		String coords = dom.getElementValue(polyElt);
		String[] coordArray = coords.split(" ");

		// read all points
		GeometryFactory fac = new GeometryFactory();
		int numPoint = coordArray.length/2;
		Coordinate[] coordinates = new Coordinate[numPoint];
		for (int p = 0; p < numPoint; p++)
		{
			Coordinate c = new Coordinate();
			c.y = Double.parseDouble(coordArray[p*2]);
			c.x = Double.parseDouble(coordArray[p*2+1]);
			coordinates[p] = c;
		}

		LinearRing outer = fac.createLinearRing(coordinates);
		Polygon poly = fac.createPolygon(outer, null);
		return poly;
	}
}
